/*
 * AsistenteObtencionDeTerminos.cpp
 *
 *  Created on: 27/11/2011
 *      Author: putaro
 */

#include "AsistenteObtencionDeTerminos.h"
#include "GeneradorDeListadoDeDirectorio.h"
#include "RutasDocumentos.h"
#include "CaracteresHandler.h"
#include "Parser.h"
/*
 * Pre:-
 * Post: Se ha creado una instancia de la clase lista para ser utilizada.
*/
AsistenteObtencionDeTerminos::AsistenteObtencionDeTerminos() {
	//Inicialización de buffer lectura
	memset(&bufferLecturaCaracteres,0,TAM_BUFFER_LECTURA);
	this -> posicionBufferLecturaCaracteres = TAM_BUFFER_LECTURA;
}

/*
 * Pre: La instancia ha sido creada.
 * Post: La instancia ha sido destruida liberando los recursos asociados.
*/
AsistenteObtencionDeTerminos::~AsistenteObtencionDeTerminos() {
}

/*
 * Pre: La instancia ha sido creada.
 * Pos: Se han recuperando los términos generando un archivo con los mismos.
 *
 */
unsigned int AsistenteObtencionDeTerminos::recuperarTerminos(
						const string & directorioArchivoRutasDocumentos ,
						const string & directorioDestino){
	unsigned int cantidadDeDocumentos = 0;
	ofstream parser1;
	//armo ruta y creo el archivo Parser1
	string rutaParser1(directorioDestino);
	rutaParser1.append("/");
	rutaParser1.append(ARCHIVO_PARSER1);
	parser1.open(rutaParser1.c_str(),ios::out | ios::binary);
	//creo la instancia que permite recuperar las rutas de
	//los documentos
	RutasDocumentos rutas(directorioArchivoRutasDocumentos);
	// carga de terminos de cada archivo
	string* rutaArchivo = rutas.readNext();
	while(rutaArchivo != NULL){
		this -> cargarTerminosArchivo(parser1,*rutaArchivo,cantidadDeDocumentos);
		delete(rutaArchivo);
		rutaArchivo = rutas.readNext();
		cantidadDeDocumentos++;
	}
	parser1.close();
	return cantidadDeDocumentos;
}

/*
 * Pre: La instancia ha sido creada y el parámetro archivo salida ha sido abierto.
 * El parámetro rutaArchivoFuente, contiene la ruta completa del archivo del cual
 * se quieren extraer todos los términos.
 *
 * Post: Se cargan todos los terminos de un archivo dado.
*/
void AsistenteObtencionDeTerminos::cargarTerminosArchivo(ofstream &salida ,
								const string & rutaArchivoFuente ,
								const unsigned int idDocumento){
	ifstream documento;
	documento.open(rutaArchivoFuente.c_str(),ios::in | ios::binary);
	if(documento.is_open()){
		string* termino = NULL;
		T_RegistroTerminos registro;
		registro.documento = idDocumento;
		termino = this -> leerTermino(documento);
		while(termino != NULL){
			registro.longitudTermino = termino -> length();
			salida.write(reinterpret_cast<char *>(&registro),sizeof(T_RegistroTerminos));
			salida<<(*termino);
			delete(termino);
			termino = NULL;
			termino = this->leerTermino(documento);
		}
	} else{
		cout<<endl<<endl<<"ERROR: No se pudo abrir "<<rutaArchivoFuente<<" "<<idDocumento<<endl<<endl;
	}
	documento.close();
}


/*
 * Pre: La instancia ha sido creada.
 * Post: Se retorna un puntero a un nuevo término.
 * Return: En caso de que no se pueda recuperar un nuevo término se retorna NULL.
 */
string* AsistenteObtencionDeTerminos::leerTermino(ifstream &archivo){
	string* retorno = NULL;
	retorno = new string();
	char caracter = 0;
	bool fin = false;
	bool isNumerico = false;
	bool isValido = false;
	//obtengo el primer caracter valido
	while (!fin){
		// si se pudo leer un caracter se verifica que sea valido
		if (this -> leerCaracter(archivo,caracter)) {
			isValido = CaracteresHandler::procesarCaracter(caracter , isNumerico ,
															*retorno, *this,archivo);
			// si no es valido se siguen leyendo caracteres
			fin = isValido;
		} else {
			// si no se pudo leer ningun caracter más se finaliza el ciclo
			fin = true;
		}
	}
	// si se logro obtener un caracter valido se inicia lectura del resto de los caracteres
	// que componen un término
	if (isValido){
		fin = false;
		//terminos alfanúmericos
		if(!isNumerico){
			// se finaliza cuando se halla un caracter que no es valido
			while (!fin){
				// si se pudo leer un caracter se verifica que sea valido
				if (this -> leerCaracter(archivo,caracter)) {
					if ( !CaracteresHandler::procesarCaracter(caracter,isNumerico,*retorno,
															*this,archivo)) {
						fin = true;
					}
				} else {
					// si no se pudo leer ningun caracter más se finaliza el ciclo
					fin = true;
				}
			}
		//terminos que inicien con números
		}else{
			// se finaliza cuando se halla un caracter que no es válido
			while (!fin){
				// si se pudo leer un caracter se verifica que sea válido
				if (this -> leerCaracter(archivo,caracter)) {
					if (!CaracteresHandler::procesarCaracter(caracter,isNumerico,*retorno,
															*this,archivo)) {
						if(retorno->length()>4){
							delete(retorno);
							retorno = NULL;
						}
						fin = true;
					}
				} else {
					// si no se pudo leer ningun caracter más se finaliza el ciclo
					if(retorno->length()>4){
						delete(retorno);
						retorno = NULL;
					}
					fin = true;
				}
			}
		}
	}else{
		delete(retorno);
		retorno = NULL;
	}
	return retorno;
}

/*
 * Pre: La instancia ha sido creada.
 * Post: El parámetro caracter tiene el siguiente caracteres leido.
 * Returns: True si se pudo leer un nuevo caracter
 */
bool AsistenteObtencionDeTerminos::leerCaracter(ifstream &archivo , char &caracter){
	bool retorno = false;
	//si se termino de leer todo el buffer y el archivo no termino
	if(this -> posicionBufferLecturaCaracteres >= TAM_BUFFER_LECTURA){
		if(!archivo.eof()){
			memset(this -> bufferLecturaCaracteres, 0 , TAM_BUFFER_LECTURA);
			archivo.read(reinterpret_cast<char *>(bufferLecturaCaracteres),TAM_BUFFER_LECTURA);
			caracter = bufferLecturaCaracteres[0];
			this -> posicionBufferLecturaCaracteres = 1;
			retorno = true;
		}
	}else{
		caracter = this->bufferLecturaCaracteres[this->posicionBufferLecturaCaracteres];
		this->posicionBufferLecturaCaracteres++;
		retorno = true;
	}
	return retorno;
}
